# coding=utf8
__author__ = 'lijian'
import logging
import os
import datetime
import json
from utils import bcdUtil

import setting
from xml.dom import minidom
from utils import byteUtil
import analogConfig
import time

_actionRecords = []

_signalTypeDict = {}

_analogUserLimitDict = {}

_analogValue = []

_signalValue = [0] * 26

_analogConfig = None

_level = 0

_todayAction = None

_pollTime = datetime.datetime.now()


def getActionRecords(month, day, count):
    startRecord = None
    for record in _actionRecords:
        if record["date"].month == month and record["date"].day == day:
            startRecord = record
            break
    start = _actionRecords.index(startRecord)

    return _actionRecords[start:start + count]


def replaceActions(actions):
    for new in actions:
        old = findActionRecord(new["date"])

        old["onTime"] = new["onTime"]
        old["offTime"] = new["offTime"]

    saveActionRecord()


def saveActionRecord():
    impl = minidom.getDOMImplementation()
    dom = impl.createDocument(None, 'actions', None)
    root = dom.documentElement

    for record in _actionRecords:
        action = dom.createElement('action')
        action.setAttribute("date", "%s" % record["date"])
        action.setAttribute("onTime", "%r" % record["onTime"])
        action.setAttribute("offTime", "%r" % record["offTime"])

        root.appendChild(action)

    f = open(setting.RTU_RECORD_PATH, 'w')
    dom.writexml(f, addindent='  ', newl='\n', encoding='utf-8')
    f.close()

    os.system("sync")


monthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def addDay(month, day):
    monthDayCount = monthDays[month - 1]
    nextDay = day + 1
    if nextDay > monthDayCount:
        return month + 1, 1
    else:
        return month, nextDay


def loadActionRecord():
    for month in range(1, 13):
        for day in range(1, monthDays[month - 1] + 1):
            key = "%d-%d" % (month, day)
            action = {"date": key, "onTime": [18, 0], "offTime": [6, 0]}
            _actionRecords.append(action)

    try:
        doc = minidom.parse(setting.RTU_RECORD_PATH)
        root = doc.documentElement

        eles = root.getElementsByTagName("action")
        for ele in eles:
            date = ele.getAttribute("date").encode("ISO-8859-1")

            onTimeStr = ele.getAttribute("onTime").encode("ISO-8859-1")
            onTime = eval(onTimeStr)

            offTimeStr = ele.getAttribute("offTime").encode("ISO-8859-1")
            offTime = eval(offTimeStr)

            action = findActionRecord(date)
            if action:
                action["onTime"] = onTime
                action["offTime"] = offTime

    except Exception as e:
        logging.error("parse %s error" % setting.RTU_RECORD_PATH)


def findActionRecord(date):
    for record in _actionRecords:
        if record["date"] == date:
            return record


def resetTodayAction():
    global _todayAction, _pollTime
    today = datetime.datetime.now()
    # _todayAction = findActionRecord(today.month, today.day)

    if _todayAction:
        _pollTime = _todayAction["onTime"]


def isPollTime():
    now = datetime.datetime.now()
    if now > _pollTime:
        return True
    else:
        return False


def getSignalType(start, count):
    global _signalTypeDict
    values = []
    for point in range(start, start + count):
        key = point
        if _signalTypeDict.has_key(key):
            values.append(_signalTypeDict[key])
        else:
            pass
    return values


def appendSignalType(paramDict):
    global _signalTypeDict
    for key, value in paramDict.items():
        _signalTypeDict[key] = value

    f = open(setting.RTU_TELE_TYPE_DICT, 'w')
    s = "%r" % _signalTypeDict
    f.write(s)
    f.close()
    os.system("sync")


def isPowerOn():
    if _level == 0:
        return False
    else:
        return True


def getLevel():
    return _level


def setLevel(value):
    global _level
    _level = value


def loadData():
    loadActionRecord()

    _loadCD1(setting.RTU_TELE_TYPE_DICT)
    _loadCD2(setting.RTU_ANALOG_LIMIT_DICT)

    global _analogConfig
    _analogConfig = analogConfig.defaultConfig

    for key, value in _analogUserLimitDict.items():
        _analogConfig[key] = value

    for point in range(81):
        analog = {"value": 0,
                  "alarm": {
                      "powerOnUpperLimit": {"status": False, "count": 0},
                      "powerOnLowerLimit": {"status": False, "count": 0},
                      "powerOffLowerLimit": {"status": False, "count": 0}
                  }
        }

        _analogValue.append(analog)


def _loadCD1(filePath):
    global _signalTypeDict
    try:
        f = open(filePath, 'r')
        txt = f.read()

        if len(txt) > 0:
            content = eval(txt)

            _signalTypeDict = content

    except:
        logging.error("load %s error" % filePath)


def _loadCD2(filePath):
    global _analogUserLimitDict
    try:
        f = open(filePath, 'r')
        txt = f.read()

        if len(txt) > 0:
            content = eval(txt)

            _analogUserLimitDict = content

    except:
        logging.error("load %s error" % filePath)


def getSignalValue(point):
    return _signalValue[point]


def setSignalValue(point, value):
    _signalValue[point] = value


def getAnalogLimitParam(start, count):
    values = []
    for point in range(start, start + count):
        key = str(point)
        if _analogConfig.has_key(key):
            values.append(_analogConfig[key])
        else:
            break
    return values


def appendAnalogLimitParam(paramDict):
    for key, value in paramDict.items():
        _analogUserLimitDict[key] = value
        _analogConfig[key] = value

    jsonDumpsIndentStr = json.dumps(_analogUserLimitDict, indent=1)

    f = open(setting.RTU_ANALOG_LIMIT_DICT, 'w')
    f.write(jsonDumpsIndentStr)
    f.close()
    os.system("sync")


def setAnalogValue(point, value):
    _analogValue[point]["value"] = value


def getAnalogValue(point):
    return _analogValue[point]["value"]


def getAnalog(point):
    return _analogValue[point]


def getAnalogConfig(point):
    key = "%d" % point
    if _analogConfig.has_key(key):
        return _analogConfig[key]
    else:
        return None


def endoceAnalogPointValue(point):
    analogValue = getAnalogValue(point)
    param = getAnalogConfig(point)

    type = param["type"]
    func = analogConfig.encodeFunc(type)
    if func:
        return func(analogValue)
    else:
        return [0, 0]

def encodeAnalog(type,value):
    func = analogConfig.encodeFunc(type)
    if func:
        return func(value)
    else:
        return [0, 0]

def decodeAnalogByPoint(point,raw):
    param = getAnalogConfig(point)

    type = param["type"]
    func = analogConfig.decodeFunc(type)
    if func:
        return func(raw)
    else:
        return [0, 0]

def decodeAnalogByType(type,raw):
    func = analogConfig.decodeFunc(type)
    if func:
        return func(raw)
    else:
        return [0, 0]

def getAnalogPointType(point):
    param = getAnalogConfig(point)
    type = param["type"]
    return type

